package com.zsrt.devbase.common.shiro;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import com.zsrt.devbase.common.utils.ConstantDefine;
import com.zsrt.devbase.common.utils.DESedeUtil;
import com.zsrt.devbase.common.utils.RegExpValidator;
import com.zsrt.devbase.common.utils.ShiroUtil;
import com.zsrt.devbase.common.utils.StringUtil;
import com.zsrt.devbase.dto.AccountDTO;
import com.zsrt.devbase.dto.FunctionInfoDTO;
import com.zsrt.devbase.service.AccountService;
import com.zsrt.devbase.service.FunctionInfoService;
/**
 * shiro登录和授权
 * @author leixin
 * @Date 2017年4月26日
 * @version 1.0
 */
public class SystemAuthorizingRealm extends AuthorizingRealm {
	private Logger logger = Logger.getLogger(this.getClass());
	/** 加密的密钥 */
	private String accountKey;

	public void setAccountKey(String accountKey) {
		this.accountKey = accountKey;
	}

	@Autowired
	private FunctionInfoService functionInfoService;
	
	private AccountService accountService;
	
	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}
	/*
	*//**
	 * 授权
	 *//*
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		AccountDTO accountDTO = (AccountDTO) principals.getPrimaryPrincipal();
		List<String> permissions = new ArrayList<String>();
		//查询权限
		List<PrivilegeDTO> listPrivilege =accountInfoService.findPrivilegesByPersonCode(accountDTO.getPersonCode());
		accountDTO.setListPrivilege(listPrivilege);
		// 添加权限
		if (listPrivilege != null) {
			for (PrivilegeDTO privilegeDTO : listPrivilege) {
				String permissionCode = privilegeDTO.getPermissionCode();
				if (!StringUtil.isBlank(permissionCode)) {
					permissions.add(privilegeDTO.getPermissionCode());
				}
			}
		}
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		simpleAuthorizationInfo.addStringPermissions(permissions);
		return simpleAuthorizationInfo;
	}

	*//**
	 * realm的认证方法，从数据库查询用户信息
	 *//*
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String userCode = (String) token.getPrincipal();
		AccountDTO accountPara = new AccountDTO();
		accountPara.setAccountCode(userCode);
		accountPara.setPersonCode(userCode);
		AccountDTO account = accountInfoService.getAccountInfo(accountPara);
		if (account == null) {
			throw new AuthenticationException("账号不存在");
		}
		if ("0".equals(account.getState())) {
			throw new AuthenticationException("账号失效，请联系管理员");
		}
		String id = account.getId();
		String accPwd = account.getAccountPwd();
		String ivSpec = id.substring(0, 8);
		// 用户登录对密码进行加密
		try {
			byte[] keyByte = DESedeUtil.getKeyByte(accountKey);
			accPwd = DESedeUtil.decryptMode(keyByte, DESedeUtil.hexStringToByte(accPwd), ivSpec);
		} catch (Exception e) {
			logger.error("decrypt fail", e);
		}
		account.setAccountPwd(null);
		// password密文，传入
		accPwd = new Md5Hash(accPwd).toHex();
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(account, accPwd,
				this.getName());
		return simpleAuthenticationInfo;
	}

	public void clearCached() {
		PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
		super.clearCache(principals);
	}*/

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		List<String> roleList = (List<String>) ShiroUtil.getSessionByKey(ConstantDefine.ROLE_SESSION);
		SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
		if (!CollectionUtils.isEmpty(roleList)) {
			List<String> permissions = new ArrayList<>();
			List<FunctionInfoDTO> funcList = functionInfoService.getFunctionAllByRoleList(roleList);
			String permissionCode = null;
			if (null != funcList) {
				for (FunctionInfoDTO function : funcList) {
					permissionCode = function.getPermissionCode();
					if (!StringUtil.isEmpty(permissionCode)) {
						permissions.add(permissionCode);
					}
				}
			}
			//存放角色、权限码
			simpleAuthorizationInfo.addStringPermissions(permissions);
			simpleAuthorizationInfo.addRoles(roleList);
			
		}
		return simpleAuthorizationInfo;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		String accountCode = (String) token.getPrincipal();
		AccountDTO para = new AccountDTO();
		boolean phone = RegExpValidator.isPhone(accountCode);
		boolean email = RegExpValidator.isEmail(accountCode);
		if (phone) {
			para.setPhone(accountCode);
		} else if (email) {
			para.setEmail(accountCode);
		} else {
			para.setAccountCode(accountCode);
		}
		para.setStatus("1");
		/**
		 * 需要在这里重写查询方法，保证查询出来的结果有状态为有效和锁定的
		 */
		AccountDTO account = accountService.selectOne(para);
		if (null == account) {
			throw new AuthenticationException("账号不存在或账号失效");
		}
		String id = account.getId();
		String accPwd = account.getPassword();
		String ivSpec = id.substring(0, 8);
		String decryptPassword = DESedeUtil.decryptMode(accountKey, accPwd, ivSpec);
		account.setPassword(null);
		// password密文，传入
		decryptPassword = new Md5Hash(decryptPassword).toHex();
		SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(account, decryptPassword,
				this.getName());
		return simpleAuthenticationInfo;
	}
	
	public void clearCached() {
		PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
		super.clearCache(principals);
	}
}
